feat(tui): replace scrap screen with component storybook - #39548
Merged
Conversation
kitlangton
force-pushed
the
tab-playground-sim
branch
from
July 29, 2026 18:17
a734323 to
7e545ff
Compare
kitlangton
force-pushed
the
tab-playground-sim
branch
2 times, most recently
from
July 29, 2026 18:33
71f7d26 to
5e844ef
Compare
kitlangton
force-pushed
the
tab-playground-sim
branch
from
July 29, 2026 19:50
5e844ef to
d553e46
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Replaces the
scrapscratch screen with a component storybook — a built-in debug plugin hosting fixture-driven, full-screen simulations of real production components — and ships a round of tab-animation polish that came out of iterating in it.Storybook
Open storybookin the palette, Debug group): lists stories,↑/↓/j/k+enteror number keys to open,eschome. Each story also gets its own palette entry (Storybook: Session tabs).● Working…, warning⚠ Permission required…, red✗ … failed, green✓ Done).spacestarts a random tab (the selected tab included);sruns the selected tab so the edge flash and sweep can be watched under the cursor. Runs randomly complete (accent unread glow), fail (red glow), or pause needing input (breathing warning glow). New tabs open untitled and earn their title with the left-to-right wipe on first completion.tadd,dclose,rreset, arrows and1–0to move, drag to reorder,escback to the index.OPENCODE_STORY=1boots into the index;OPENCODE_STORY=session-tabsboots straight into a story. This replacesOPENCODE_SCRAP, whose route id (scrapinstead ofopencode.scrap) had been broken since the flag was introduced.Animation polish (production)
blendTabPulseColor, instead of sharing the running stage's color.unreadGlowIntensity), strongest by the number and neutral ~10 cells in. Non-glowing, non-fading titles still render as one plain string.TabPulsereports the sweep's level at the number cell through a quantizedonLevelcallback (1/32 steps, 0 on idle), so updates only fire on visible change.initialRoutevalidation preserved plugin routes but silently dropped theirdata, breaking any deep link into a plugin page (includingOPENCODE_STORY=<id>andOPENCODE_ROUTE-injected routes). Fixed incontext/route.tsx.How
feature-plugins/system/storybook/index.tsx: theStorytype ({ id, title, render }), the story registry, the index screen, and the palette commands. Stories own their whole screen and bindescback to the index. One plugin route (storybook) renders a story whendata.storymatches, the index otherwise.feature-plugins/system/storybook/session-tabs.tsx: the tab lifecycle simulation plus the fake transcript. Fixture state lives in a keyed store (mirroring production identity semantics); a per-sessionoutcomesrecord remembers how the last run ended, since unread state clears on select.component/tab-pulse.tsx:flashColoroption and blend stage;EDGE_FLASH_ATTACK; longer durations;onLevelemission from the render pass.component/session-tabs.tsx:flashColorwiring, per-charactercharacterColor(glow tinge + long-title fade share one code path),sweepLevelsignal feedingnumberColor.context/route.tsx: plugin startup routes keep theirdata.plugin/builtins.ts: registersopencode.storybookin place ofopencode.scrap. Like all builtins it can be disabled withplugins: ["-opencode.storybook"].app.tsx: theOPENCODE_STORYstartup route replacesOPENCODE_SCRAP.Scope
Follow-up to #39542 (previously stacked as #39546, auto-closed when the base branch merged). A pulse-variant A/B story was used to evaluate six alternative sweep animations and removed after the current sweep won; only the number pulse survived from that exploration. Adding stories for other components (and the controller seams they need) is future work.
Testing
bun typecheckinpackages/tuibun run testinpackages/tui: 579 passed, 5 skipped (blend equivalence test extended to the four-stage pipeline; completion-pulse shape test updated for the new attack fraction)Demo
See the recording on #39542: it drives an earlier revision of the session-tabs story end to end.